
/*
 *   SSCatalystComment.m
 *  MESLib
 * 
 * Copyright 2003-2009 Starline Software Ltd
 * 
 * This file is part of MESLib.
 * 
 * MESLib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MESLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with MESLib. If not, see <http://www.gnu.org/licenses/>.
 */
//  Created by Tobias Haughton on Mon Jan 27 2003.
//

#import "SSCatalystComment.h"
#import "SSCatalystDocument.h"

@implementation SSCatalystComment

- (id)initWithUnique_id:(NSString *)idString
                comment:(NSString *)comment
                   type:(NSNumber *)t
               position:(NSPoint)p
         closestEvent:(NSString *)ce
     closestEventOffset:(NSPoint)ceOffSet
{
   if (self = [super init]) {
      isLoading = YES;
      [self setUnique_id:idString];
      [self setType:t];
      [self setCommentString:comment];
      [self setClosestEvent:ce];
      [self setClosestEventOffset:ceOffSet];

      commentView = [[SSCommentView alloc] initWithFrame:NSMakeRect(p.x, p.y, SSCommentViewSize.width, SSCommentViewSize.height)
                                                  string:comment
                                                    type:t
                                                   owner:self];
      
      isVisible = YES;
      isLoading = NO;
   }
   return self;
}

- (id)initWithUnique_id:(NSString *)idString
                comment:(NSString *)comment
                   type:(NSNumber *)t
               position:(NSPoint)p
{
   if (self = [super init]) {
      isLoading = YES;
      [self setUnique_id:idString];
      [self setType:t];
      [self setCommentString:comment];
      
      commentView = [[SSCommentView alloc] initWithFrame:NSMakeRect(p.x, p.y, SSCommentViewSize.width, SSCommentViewSize.height)
                                                  string:comment
                                                    type:t
                                                   owner:self];
      
      isVisible = YES;
      isLoading = NO;
   }
   return self;
}

- (id)initWithPboardRepresentation:(NSMutableDictionary *)dict origin:(NSPoint)point
{
   if (self = [super init]) {
      isLoading = YES;
      [self setUnique_id:[dict objectForKey:@"unique_id"]];
      [self setType:[dict objectForKey:@"type"]];
      [self setCommentString:[dict objectForKey:@"commentString"]];
      
      commentView = [[SSCommentView alloc] initWithFrame:NSMakeRect(point.x, point.y, SSCommentViewSize.width, SSCommentViewSize.height)
                                                  string:[self commentString]
                                                    type:[self type]
                                                   owner:self];
      
      isVisible = YES;
      isLoading = NO;
   }
   return self;
}

- (NSString *)unique_id
{
   return unique_id;
}

- (void)setUnique_id:(NSString *)string
{
   [unique_id release];
   [string retain];
   unique_id = string;
}

- (void)setCommentString:(NSString *)string;
{
   [commentString release];
   [string retain];
   commentString = string;

   [commentView updateCommentString];

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSCommentDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setType:(NSNumber *)number
{
   [type release];
   [number retain];
   type = number;

   [commentView setCommentImage];

   if(!isLoading) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"SSCommentDataChanged"
                                                          object:nil];
      [[[NSDocumentController sharedDocumentController] currentDocument] updateChangeCount:NSChangeDone];
   }
}

- (void)setCommentView:(SSCommentView *)view
{
   [commentView release];
   [view retain];
   commentView = view;
}


- (NSNumber *)type
{
   return type;   
}

- (NSString *)typeString
{
   switch([[self type] intValue]) {
      case SSCommentQuestionType:return @"question";
           break;
      case SSCommentNoteType:return @"note";
           break;
      default:return @"alert";
         break;
   }
}

- (NSString *)commentString
{
   return commentString;   
}

- (SSCommentView *)commentView
{
   return commentView;   
}

- (float)xPosition
{
   return NSMinX([[self commentView] frame]);   
}

- (NSString *)xPositionString
{
   return [[NSNumber numberWithFloat:NSMinX([[self commentView] frame])] stringValue];
}

- (float)yPosition
{
    return NSMinY([[self commentView] frame]);   
}

- (NSString *)yPositionString
{
   return [[NSNumber numberWithFloat:NSMinY([[self commentView] frame])] stringValue];
}

- (void)setXPosition:(float)xPos
{
   [commentView setFrameOrigin:NSMakePoint(xPos, NSMinY([commentView frame]))];
}

- (void)setYPosition:(float)yPos
{
   [commentView setFrameOrigin:NSMakePoint(NSMinX([commentView frame]), yPos)];
}

- (NSPoint)closestEventOffset
{
   return closestEventOffset;
}

- (void)setClosestEventOffset:(NSPoint)point
{
   closestEventOffset = point;
}

- (void)setClosestEvent
{
   NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

   [nc removeObserver:self
                 name:@"NSViewFrameDidChangeNotification"
               object:[linkedEvent eventView]];
   
   closestEvent = [[[NSDocumentController sharedDocumentController] currentDocument] closestEventToComment:self];
   [self setClosestEventOffset:NSMakePoint((NSMinX([commentView frame]) - NSMinX([closestEvent frame])),
                                           (NSMinY([commentView frame]) - NSMinY([closestEvent frame])))];

   if([closestEvent isKindOfClass:[SSEventObject class]]) {
      [self setClosestEventOffset:NSMakePoint((NSMinX([commentView frame]) - NSMinX([closestEvent frame])),
                                              (NSMinY([commentView frame]) - NSMinY([closestEvent frame])))];

      [nc addObserver:self
             selector:@selector(followClosestEvent)
                 name:@"NSViewFrameDidChangeNotification"
               object:[closestEvent eventView]];
   }
}

- (void)setClosestEvent:(id)ce
{
   NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

   [nc removeObserver:self
                 name:@"NSViewFrameDidChangeNotification"
               object:[linkedEvent eventView]];

   closestEvent = ce;

   if([closestEvent isKindOfClass:[SSEventObject class]]) {
      [self setClosestEventOffset:NSMakePoint((NSMinX([commentView frame]) - NSMinX([closestEvent frame])),
                                              (NSMinY([commentView frame]) - NSMinY([closestEvent frame])))];

      [nc addObserver:self
             selector:@selector(followClosestEvent)
                 name:@"NSViewFrameDidChangeNotification"
               object:[closestEvent eventView]];
   }
}

- (id)closestEvent
{
   return closestEvent;
}

- (BOOL)isVisible
{
   return isVisible;
}

- (void)setIsVisible:(BOOL)b
{
   isVisible = b;
}

- (void)followClosestEvent
{
   if([closestEvent isKindOfClass:[SSEventObject class]]) {
      NSPoint newOrigin = NSMakePoint((NSMinX([[closestEvent eventView] frame]) + closestEventOffset.x),
                                      (NSMinY([[closestEvent eventView] frame]) + closestEventOffset.y));
      [commentView setNewOriginWithPoint:newOrigin];
   }
}

- (NSMutableDictionary *)pastboardRepresentation
{
   NSMutableDictionary *dict = [NSMutableDictionary dictionary];
   [dict setObject:[self class] forKey:@"objectType"];
   [dict setObject:unique_id forKey:@"unique_id"];
   [dict setObject:type forKey:@"type"];
   [dict setObject:commentString forKey:@"commentString"];

   return dict;
}

//***********************************xml string
- (NSString *)xmlStringRepresentation
{
   NSString *xmlString = [NSString stringWithFormat:@"\t<comment unique_id=\"%@\" type=\"%@\">\n\t\t<text>%@</text>\n\t\t<position>\n\t\t\t<x unit=\"pixels\">%f</x>\n\t\t\t<y unit=\"pixels\">%f</y>\n\t\t</position>\n\t\t<closest_event unique_id=\"%@\">\n\t\t\t<closest_event x_offset>%f</closest_event x_offset>\n\t\t\t<closest_event y_offset>%f</closest_event y_offset>\n\t\t</closest_event>\n\t</comment>",
      [self unique_id], [self typeString], commentString, NSMinX([commentView frame]), NSMinY([commentView frame]),
      [closestEvent unique_id], [self closestEventOffset].x, [self closestEventOffset].y];

   return xmlString;
}

//***********************************coding
- (void)encodeWithCoder:(NSCoder *)coder
{
   [coder encodeObject:[self unique_id] forKey:@"unique_id"];
   [coder encodeObject:[self commentString] forKey:@"commentString"];
   [coder encodeObject:[self type] forKey:@"type"];
   [coder encodeObject:[self commentView] forKey:@"commentView"];
   [coder encodeObject:closestEvent forKey:@"closestEvent"];
   [coder encodePoint:closestEventOffset forKey:@"closestEventOffset"];
}

- (id)initWithCoder:(NSCoder *)coder
{
   if(self = [super init]) {
      [self setUnique_id:[coder decodeObjectForKey:@"unique_id"]];
      [self setType:[coder decodeObjectForKey:@"type"]];
      [self setCommentString:[coder decodeObjectForKey:@"commentString"]];
      [self setCommentView:[coder decodeObjectForKey:@"commentView"]];

      if([coder containsValueForKey:@"closestEvent"]) {
         [self setClosestEvent:[coder decodeObjectForKey:@"closestEvent"]];
         [self setClosestEventOffset:[coder decodePointForKey:@"closestEventOffset"]];
      }

      isVisible = YES;
   }

   return self;
}

//***********************************

- (void)dealloc
{
   [[NSNotificationCenter defaultCenter] removeObserver:self];
   
   [unique_id release];
   [commentView release];
   [type release];
   [commentString release];
   [super dealloc];
}

@end
